#include "domainnamesystem.h"

DomainNameSystem::DomainInfo::DomainInfo(const QString &name,const QString &IP,const QString &owner,const QString &notes)
    :name{name},IP{IP},owner{owner},notes{notes} {}

DomainNameSystem::DomainInfo::DomainInfo(const DomainInfo &info)
    :name{info.name},IP{info.IP},owner{info.owner},notes{info.notes} {}

DomainNameSystem::DomainNode::DomainNode(const QString &name)
    :name{name},firstSon{nullptr},rightBro{nullptr},info{nullptr} {}

DomainNameSystem::DomainNameSystem() {
    root=new DomainNode("");
}

DomainNameSystem::~DomainNameSystem() {
    deleteTree(root);
}

DomainNameSystem& DomainNameSystem::DNS(){
    static DomainNameSystem DNS;
    return DNS;
}

bool DomainNameSystem::isValidDomain(const QString &domain){
    if(!domain.contains('.')) return false;
    QStringList labels=domain.split(".");
    for(const QString &label:labels){
        if(label.length()<1||label.length()>63) return false;
        if(label.startsWith('-')||label.endsWith('-')) return false;
        for(QChar c:label)
            if(!c.isLetterOrNumber()&&c!='-') return false;
    }
    QString topLevelDomain=labels.last();
    if(topLevelDomain.length()<2) return false;
    return true;
}

void DomainNameSystem::insertDomain(const QString &domain,const DomainInfo &info){
    addDomainToTree(domain,info,root);
}

void DomainNameSystem::displayDomains(){
    inOrderTraversal(root);
}

void DomainNameSystem::saveDomains(QTextStream &out){
    writeDomainToFile(out,root);
}

void DomainNameSystem::readDomains(QTextStream &in){
    readDomainFromFile(in,root);
}

void DomainNameSystem::deleteTree(DomainNode *node){
    if(node){
        deleteTree(node->firstSon);
        deleteTree(node->rightBro);
        delete node;
    }
}

void DomainNameSystem::addDomainToTree(const QString &domain,const DomainInfo &info,DomainNode *node){
    if(!node) return;
    QStringList labels=domain.split('.');
    for(auto label=labels.rbegin();label!=labels.rend();label++){
        DomainNode* current=node->firstSon;
        while(current){
            if(current->name==*label){
                node=current;
                break;
            }
            current=current->rightBro;
        }
        if(!current){
            DomainNode* newNode=new DomainNode(*label);
            newNode->rightBro=node->firstSon;
            node->firstSon=newNode;
            node=newNode;
        }
    }
    if(node->info==nullptr){
        node->info=new DomainInfo(info);
    }
    //目前未考虑重复插入情况
}

void DomainNameSystem::inOrderTraversal(DomainNode *node){
    if(node){
        inOrderTraversal(node->firstSon);
        qDebug()<<node->name;
        if(node->info) qDebug()<<node->info->name<<node->info->IP<<node->info->owner<<node->info->notes;
        inOrderTraversal(node->rightBro);
    }
}

void DomainNameSystem::writeDomainToFile(QTextStream &out,DomainNode *node){
    if(node){
        writeDomainToFile(out,node->firstSon);
        if(node->info){
            QString info=node->info->name +"#"
                        +node->info->IP   +"#"
                        +node->info->owner+"#"
                        +node->info->notes+"\n";
            out<<info;
        }
        writeDomainToFile(out,node->rightBro);
    }
}

void DomainNameSystem::readDomainFromFile(QTextStream &in,DomainNode *node){
    while(!in.atEnd()){
        QString text=in.readLine();
        QStringList parts=text.split("#");
        if(parts.size()==DomainInfo::dataNum){
            QString name=parts[0];
            QString IP=parts[1];
            QString owner=parts[2];
            QString notes=parts[3];
            DomainInfo info(name,IP,owner,notes);
            addDomainToTree(name,info,node);
        }
    }
}
